﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;

namespace WindowsFormsApp1
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (OpenApp.ShowDialog(this) == DialogResult.OK)
            {
                txtAppFullPath.Text = OpenApp.FileName;

                var fileInfo = new FileInfo(OpenApp.FileName);

                if (fileInfo.Exists)
                {

                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            foreach (var process in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(OpenApp.FileName)))
            {
                try
                {
                    if (process.MainModule != null && process.MainModule.FileName.Equals(OpenApp.FileName))
                    {
                        process.Kill();
                    }
                }
                catch (Exception exp)
                {
                    MessageBox.Show(exp.Message);
                }
            }

            LoadExeApp(OpenApp.FileName);
        }

        #region 内嵌处理

        private Action<object, EventArgs> appIdleAction = null;
        private EventHandler appIdleEvent = null;
        private Process AppProcess { get; set; }
        private TabPage ExePage { get; set; }

        /// <summary>
        /// 加载Exe程序
        /// </summary>
        /// <param name="app"></param>
        public void LoadExeApp(string appPath)
        {
            try
            {
                foreach (var process in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(appPath)))
                {
                    try
                    {
                        if (process.MainModule != null && process.MainModule.FileName.Equals(appPath))
                        {
                            process.Kill();
                        }
                    }
                    catch (Exception exp)
                    {
                        MessageBox.Show(exp.Message);
                    }
                }

                ProcessStartInfo info = new ProcessStartInfo(appPath)
                {
                    UseShellExecute = true,
                    WindowStyle = ProcessWindowStyle.Minimized,
                    CreateNoWindow =false,
                };

                AppProcess = Process.Start(info);


                AppProcess.WaitForExit(3000);

                appIdleAction = new Action<object, EventArgs>(Application_Idle);
                appIdleEvent = new EventHandler(appIdleAction);
                Application.Idle += appIdleEvent;

                AppProcess.WaitForInputIdle();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
            }
        }

        /// <summary>
        /// 关联进程进入空闲状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Application_Idle(object sender, EventArgs e)
        {
            //子程序是否启动
            if (AppProcess == null || AppProcess.HasExited)
            {
                AppProcess = null;
                Application.Idle -= appIdleEvent;
                return;
            }

            //等待子程序界面加载
            Stopwatch swatch = new Stopwatch();
            swatch.Start(); //计时开始
            while (AppProcess.MainWindowHandle == IntPtr.Zero)
            {
                Thread.Sleep(100);
                AppProcess.Refresh();

                var elapsedMilliseconds = swatch.ElapsedMilliseconds;

                if (elapsedMilliseconds > 1000 * 10)
                {
                    swatch.Reset();
                    break;
                }
            }

            if (AppProcess.MainWindowHandle != IntPtr.Zero)
            {
                //进行嵌套，以及界面处理
                if (EmbedProcess(AppProcess, splitContainer1.Panel2))
                {
                    Application.Idle -= appIdleEvent;
                }
            }
        }

        public int embedResult = 0;

        /// <summary>
        /// 内嵌程序
        /// </summary>
        /// <param name="app"></param>
        /// <param name="control"></param>
        /// <returns></returns>
        private bool EmbedProcess(Process app, Control control)
        {
            // Get the main handle
            if (app == null || app.MainWindowHandle == IntPtr.Zero || control == null)
            {
                return false;
            }

            embedResult = 0;

            try
            {
                // Put it into this container
                embedResult = Win32API.SetParent(app.MainWindowHandle, control.Handle);
            }
            catch (Exception)
            { }
            try
            {
                // Remove border and whatnot
                Win32API.SetWindowLong(new HandleRef(this, app.MainWindowHandle), Win32API.GWL_STYLE, Win32API.WS_VISIBLE);
                //Win32API.SendMessage(app.MainWindowHandle, Win32API.WM_SETTEXT, IntPtr.Zero, Win32API.strGUID);
            }
            catch (Exception)
            { }
            try
            {
                // Move the window to overlay it on this window
                Win32API.MoveWindow(app.MainWindowHandle, 0, 0, control.Width, control.Height, true);
            }
            catch (Exception)
            { }

            return (embedResult != 0);
        }

        /// <summary>
        /// 内嵌插件
        /// </summary>
        private bool EmbedPlugIn(IntPtr plugInMainWindowHandle, Control control)
        {
            // Get the main handle
            if (plugInMainWindowHandle == null || plugInMainWindowHandle == IntPtr.Zero || control == null)
            {
                return false;
            }

            embedResult = 0;

            try
            {
                // Put it into this container
                embedResult = Win32API.SetParent(plugInMainWindowHandle, control.Handle);
            }
            catch (Exception)
            { }
            try
            {
                // Remove border and whatnot
                Win32API.SetWindowLong(new HandleRef(this, plugInMainWindowHandle), Win32API.GWL_STYLE, Win32API.WS_VISIBLE);
            }
            catch (Exception)
            { }
            try
            {
                // Move the window to overlay it on this window
                Win32API.MoveWindow(plugInMainWindowHandle, 0, 0, control.Width, control.Height, true);
            }
            catch (Exception)
            { }
            return (embedResult != 0);
        }

        #endregion 内嵌Exe
    }
}
